package biback.domain.customer

import biback.domain._
import biback.domain.product.SaleableProduct
import biback.utils._
import cats.Monad

import scala.collection.immutable.SortedMap

trait PersonalAlgebra[F[_]] {
  val customer: PersonalAlgebra.Service[F]
}

object PersonalAlgebra {

  trait Service[F[_]] extends GeneralAlgebra[F] {
    def getNo(acctId: AccountId)(implicit F: Monad[F]): ErrOrF[Option[CustomerNo]] =
      orF(Left(MethodNoImplement("getNo")))

    def getNoByMobile(mobile: Mobile)(implicit F: Monad[F]): ErrOrF[Option[CustomerNo]] =
      orF(Left(MethodNoImplement("getNoByMobile")))

    def createNo(catalog: CustomerCatalog)(implicit F: Monad[F]): ErrOrF[CustomerNo] =
      orF(Left(MethodNoImplement("createNo")))

    def createAcctId()(implicit F: Monad[F]): ErrOrF[AccountId] =
      orF(Left(MethodNoImplement("createAcctId")))

    def createAcctNo()(implicit F: Monad[F]): ErrOrF[AccountNo] =
      orF(Left(MethodNoImplement("createAcctNo")))

    def foundCustomerProduct(acctId: AccountId, subAcctNo: SubAccountNo)(implicit F: Monad[F]): ErrOrF[CustomerProduct] =
      orF(Left(MethodNoImplement("foundCustomerProduct")))

    def foundCustomerBase(idType: PersonalIdType, idNo: IdNo)(implicit F: Monad[F]): ErrOrF[CustomerBase] =
      orF(Left(MethodNoImplement("foundCustomerBase")))

    def foundNoByMobile(mobile: Mobile)(implicit F: Monad[F]): ErrOrF[CustomerNo] =
      foundF(getNoByMobile(mobile), NoRegistration(mobile))

    def foundNo(acctId: AccountId)(implicit F: Monad[F]): ErrOrF[CustomerNo] =
      foundF(getNo(acctId), CustomerNotFound(acctId))

    def notRegistered(mobile: Mobile)(implicit F: Monad[F]): ErrOrNoneF =
      notFoundF(getNoByMobile(mobile), MobileRegistered(mobile))

    def getSubAcctBalanceChanges(acctId: AccountId, subAcctNo: SubAccountNo, to: TrnDate)(implicit F: Monad[F]): ErrOrF[SubAcctBalanceChanges] =
      orF(Left(MethodNoImplement("getSubAcctBalanceChanges")))
  }

}

case class CustomerProduct(cNo: CustomerNo, product: SaleableProduct)

case class CustomerBase(cNo: CustomerNo, mobile: Mobile)

case class SubAcctBalanceChanges(from: TrnDate, changes: SortedMap[TrnDate, BigDecimal])
